package com.tszs.Controller;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.util.List;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContexts;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.tszs.biz.DistributorBiz;
import com.tszs.biz.UserAccessTokenBiz;
import com.tszs.biz.UserDetailsBiz;
import com.tszs.biz.UserTableBiz;
import com.tszs.entity.Distributor;
import com.tszs.entity.DistributorExample;
import com.tszs.entity.UserAccessToken;
import com.tszs.entity.UserAccessTokenExample;
import com.tszs.entity.UserDetails;
import com.tszs.entity.UserDetailsExample;
import com.tszs.entity.UserTable;
import com.tszs.entity.UserTableExample;
import com.tszs.util.CallBack;
import com.tszs.util.MD5keyBean;
import com.tszs.util.PayCommonUtil;
import com.tszs.util.Uuid;
import com.tszs.util.projectPath;
import com.tszs.WeChatUtils.Params;
import com.tszs.WeChatUtils.Sign;
import net.sf.json.JSONObject;

/**
 * @类描述：微信获取个人信息，订单支付，查询，退款，等功能
 * @author Administrator
 *
 */
@SuppressWarnings("deprecation")
@Controller
public class WeChatConytoller {

	/**
	 * @UserAccessTokenBiz
	 */
	@Autowired
	private UserAccessTokenBiz aserAccessTokenBiz;
	/**
	 * @UserDetailsBiz
	 */
	@Autowired
	private UserDetailsBiz userDetailsBiz;
	/**
	 * @UserTableBiz
	 */
	@Autowired
	private UserTableBiz userTableBiz;
	
	@Autowired
	private DistributorBiz distributorBiz;
	
	/**
	 * @方法名: MultiCompanyRegistration
	 * @方法描述:用户同意授权，获取code
	 * @创建时间: 2019-03-21 11:49:11
	 * @author: 王俊
	 * @return: 0失败 1成功
	 */
	@RequestMapping("WeChat/login")
	public void MultiCompanyRegistration_openid(HttpServletRequest request, HttpServletResponse response)
			throws IOException {
		
		String value = (String) request.getParameter("id");
		//查找出店铺名称
		
		Distributor selectByExample = distributorBiz.selectByDidentification(value);
		if (selectByExample != null) {
			request.getSession().setAttribute("distributionName",selectByExample.getdName());
			request.getSession().setAttribute("distributionId",value);
		} else {
			request.getSession().setAttribute("distributionName","天祥瑞饲料");
			request.getSession().setAttribute("distributionId","");
		}
		
		request.getSession().setAttribute("path", projectPath.url);
		response.sendRedirect("https://open.weixin.qq.com/connect/oauth2/authorize?appid=" + Params.AppID
				+ "&redirect_uri=" + Params.SysTemUrl + "WeChat/accessToken.do?"
				+ "&response_type=code&scope=snsapi_userinfo&state=STATE&connect_redirect=1#wechat_redirect");
		request.getSession().setAttribute("dDistributionIdentification",request.getParameter("dDistributionIdentification")+"");
	}

	/**
	 * @方法名: userdatails
	 * @方法描述:获取用户openid
	 * @创建时间: 2019-03-21 11:49:11
	 * @author: 王俊
	 * @return 
	 * @return 
	 * @return: 0失败 1成功
	 */
	@RequestMapping(value="WeChat/accessToken")
	public void userdatails(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		response.setContentType("text/xml; charset=UTF-8");
		String oauth2Url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=" + Params.AppID + "&secret="
				+ Params.AppSecret + "&code=" + request.getParameter("code") + "&grant_type=authorization_code"; // 获取当前用户的openid
		String Str=Params.httpsGet(oauth2Url);
		com.alibaba.fastjson.JSONObject json=com.alibaba.fastjson.JSONObject.parseObject(Str);
		String openid = json.getString("openid");
		System.out.println(openid);
		String access_token = (String) json.getString("access_token");
		String snsapi_userinfo = ("https://api.weixin.qq.com/sns/userinfo?access_token=" + access_token + "&openid="
				+ openid + "&lang=zh_CN");
		com.alibaba.fastjson.JSONObject json2=com.alibaba.fastjson.JSONObject.parseObject( Params.httpsGet(snsapi_userinfo));
		String nickname=json2.getString("nickname");//用户昵称
		String headimgurl=json2.getString("headimgurl");//图片url
		String sex=json2.getString("sex");//为1时是男性，值为2时是女性，值为0时是未知
		// openid; 用户的唯一标识  nickname 
		// sex;/// js2.getString("country");// 所在地址js2.getString("province"); 所在地址
		//// js2.getString("city");// 所在地址 headimgurl; 
		List<UserDetails>list=insert(openid,URLEncoder.encode(nickname, "utf-8"), headimgurl, sex);
		request.getSession().setAttribute("openid",list.get(0).getuOpenid());
		request.getSession().setAttribute("nickname",URLDecoder.decode(list.get(0).getuNikename(), "utf-8"));
		request.getSession().setAttribute("photo",list.get(0).getuPhoto());
		//这里不能直接跳转到真实页面地址，跳转到新页面，在在新页面跳转到真实页面地址，搭桥就在这里  init.jsp就是桥，不然会js css加载不过去   乱了  抽烟
		response.sendRedirect(Params.SysTemUrl+"init.jsp");
	}
	public List<UserDetails> insert(String openid, String uNikename, String uPhoto, String uSex) {
		UserTableExample example = new UserTableExample();
		com.tszs.entity.UserTableExample.Criteria ca = example.createCriteria();
		ca.andUNameEqualTo(openid);
		List<UserTable> selectByExample = userTableBiz.selectByExample(example);
		if (selectByExample.size() > 0) {
			/**
			 * @openID存在反出页面
			 */
			UserDetailsExample userDetailsExample = new UserDetailsExample();
			com.tszs.entity.UserDetailsExample.Criteria ca1 = userDetailsExample.createCriteria();
			ca1.andUIdEqualTo(selectByExample.get(0).getuId());
			List<UserDetails> selectByExampleuserDetails = userDetailsBiz.selectByExample(userDetailsExample);
			return selectByExampleuserDetails;
		} else {
			/**
			 * @模拟注册保存用户
			 */
			String id = Uuid.getUUID();
			String time = Uuid.getTime();
			UserTable record = new UserTable();
			record.setuId(id);
			record.setuName(openid);
			MD5keyBean m = new MD5keyBean();
			String md5 = m.getkeyBeanofStr(openid);
			record.setuPass(md5);
			record.setuCreateTime(time);
			record.setuStatic("0");
			/**
			 * @用户详情
			 */
			UserDetails record2 = new UserDetails();
			record2.setuId(id);
			record2.setuCreateTime(time);
			record2.setuStaic("0");
			record2.setuNikename(uNikename);
			record2.setuPhoto(uPhoto);
			record2.setuSex(uSex);
			record2.setuOpenid(openid);
			userDetailsBiz.insertSelective(record2);
			userTableBiz.insertSelective(record);
			UserDetailsExample userDetailsExample = new UserDetailsExample();
			com.tszs.entity.UserDetailsExample.Criteria ca1 = userDetailsExample.createCriteria();
			ca1.andUIdEqualTo(id);
			List<UserDetails> selectByExampleuserDetails = userDetailsBiz.selectByExample(userDetailsExample);
			return selectByExampleuserDetails;
		}
	}

	/**
	 * @方法名称：jsapiTicket
	 * @方法描述：用第一步拿到的access_token 采用http
	 *                           GET方式请求获得jsapi_ticket（有效期7200秒，开发者必须在自己的服务全局缓存jsapi_ticket）
	 * @return
	 */
	public String jsapiTicket(String URL, String access_token) {
		String jsapiTicket = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=" + access_token
				+ "&type=jsapi";
		String JsapiTicket = Params.httpsGet(jsapiTicket);
		JSONObject js = JSONObject.fromObject(JsapiTicket);
		String url = URL;
		Map<String, String> params = Sign.sign(js.getString("ticket"), url);
		params.put("appid", Params.AppID);
		JSONObject jsonObject = JSONObject.fromObject(params);
		String jsonStr = jsonObject.toString();
		return jsonStr;
	}

	/**
	 * @方法名: testasdsadasdsadas
	 * @方法描述: 统一下单支付成功
	 * @创建时间: 通过config接口注入权限验证配置
	 * @author: 王俊
	 * @return: 0失败 1成功
	 */
	@RequestMapping("WeChat/accessToken/testasdsadasdsadas")
	public void openid(HttpServletRequest request, HttpServletResponse response) throws IOException {
		UserAccessTokenExample example = new UserAccessTokenExample();
		List<UserAccessToken> selectByExamp = aserAccessTokenBiz.selectByExample(example);
		JSONObject js2 = JSONObject.fromObject(selectByExamp.get(0).getaAccessToken());
		String access_token = js2.getString("access_token");
		String url = request.getParameter("url");
		String json = new WeChatConytoller().jsapiTicket(url, access_token);
		response.getWriter().print(json);
	}

	/**
	 * @方法名: Order
	 * @方法描述: 统一下单支付成功
	 * @创建时间: 2019-03-21 11:49:11
	 * @author: 王俊
	 * @return: 0失败 1成功
	 */
	@RequestMapping("WeChat/accessToken/Order")
	public void Order(HttpServletRequest request, HttpServletResponse response) throws Exception {
		String mch_id = Params.MchId;// 商户号
		String nonce_str = Params.getRandomString(32);// 随机字符串
		String sign = "";// 签名
		String body = "最后一遍测试";// body
		String detail = "测试——王俊";// 商品详情
		String out_trade_no = "ceshiwangjun002";// 商户订单号
		String total_fee = "10";// 标价金额
		String spbill_create_ip = Params.getIpAddr(request);// 终端IP
		String notify_url = "tszs/WeChat/accessToken/orderquery.do";// 通知地址
		String trade_type = "JSAPI";// 交易类型
		String openid = "oqqrN54lkwFz7nHEcA56Ja0lpK2w";// 用户标识
		SortedMap<String, String> map = new TreeMap<String, String>();
		map.put("appid", Params.AppID);
		map.put("mch_id", mch_id);
		map.put("nonce_str", nonce_str);
		map.put("sign_type", Params.signType);
		map.put("body", body);
		map.put("detail", detail);
		map.put("out_trade_no", out_trade_no);
		map.put("total_fee", total_fee);
		map.put("spbill_create_ip", spbill_create_ip);
		map.put("notify_url", notify_url);
		map.put("trade_type", trade_type);
		map.put("openid", openid);
		sign = PayCommonUtil.createSign("UTF-8", map, Params.partnerkey);
		map.put("sign", sign);
		// 统一下单 https://api.mch.weixin.qq.com/pay/unifiedorder
		String url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
		// 封装xml报文
		Map<?, ?> map2 = Params.xmlToMap(Params.HttpPost(url, Params.mapToXml(map)));
		SortedMap<String, String> map3 = new TreeMap<String, String>();
		map3.put("appId", map2.get("appid") + "");
		map3.put("timeStamp", Params.create_timestamp());
		map3.put("nonceStr", map2.get("nonce_str") + "");
		map3.put("package", "prepay_id=" + map2.get("prepay_id"));
		map3.put("signType", Params.signType);
		String Paysign = PayCommonUtil.createSign("UTF-8", map3, Params.partnerkey);
		map3.put("paySign", Paysign);
		JSONObject jsonObject = new JSONObject();
		jsonObject.put("appId", Params.AppID);
		jsonObject.put("timeStamp", map3.get("timeStamp"));
		jsonObject.put("nonceStr", map3.get("nonceStr"));
		jsonObject.put("wpackage", map3.get("package"));
		jsonObject.put("signType", Params.signType);
		jsonObject.put("paySign", map3.get("paySign"));
		response.getWriter().print(jsonObject.toString());

	}

	/**
	 * @方法名: orderquery
	 * @方法描述: 订单查询/ 由于微信 官方文档 res.err_msg将在用户支付成功后返回    ok，但并不保证它绝对可靠。     so也走这个接口进行测试了
	 * @创建时间: 2019-03-21 11:49:11
	 * @author: 王俊
	 * @return: 0失败 1成功
	 */
	@RequestMapping("WeChat/accessToken/orderqueryPay")
	public static void wechatRefund1(HttpServletResponse response,HttpServletRequest request) throws Exception {
		SortedMap<String, String> map = new TreeMap<String, String>();
		map.put("appid", Params.AppID);// 公众账号ID
		map.put("mch_id", Params.MchId);// 商户号
		map.put("out_trade_no", "ceshiwangjun002");// 商户订单号
		map.put("nonce_str", Params.getRandomString(32));// 随机字符串
		map.put("sign_type", "MD5");//签名
		String sign = PayCommonUtil.createSign("UTF-8", map,  Params.partnerkey);
		map.put("sign", sign);// 签名
		System.out.println("参数封装："+map);
		String url = "https://api.mch.weixin.qq.com/pay/orderquery";
		// 封装xml报文
		Map<?, ?> map2 = Params.xmlToMap(Params.HttpPost(url, Params.mapToXml(map)));
		System.out.println(Params.mapToXml(map));
		System.err.println("查询订单返回" + map2);
		 if(map2.get("result_code").equals("SUCCESS")) {
			 if(map2.get("trade_state_desc").equals("支付成功")) {
				 new CallBack().yes(response, "","支付成功");
			 }else {
				 new CallBack().no(response, "","支付失败");
			 }
		 }else {
			 new CallBack().no(response, "","支付失败");
		 }
	}

	/**
	 * @方法名: refund
	 * @方法描述: 申请退款
	 * @创建时间: 2019-03-21 11:49:11
	 * @author: 王俊
	 * @return: 0失败 1成功
	 * @throws Exception 
	 */
	@RequestMapping("tuikuan")
	public void refund() throws Exception {
		System.out.println("退款进入");
		int total_fee = (int) (10);// 订单的总金额,以分为单位（填错了貌似提示：同一个out_refund_no退款金额要一致）
		int refund_fee = (int) (10);
		;// 退款金额，以分为单位（填错了貌似提示：同一个out_refund_no退款金额要一致）
		SortedMap<String, String> refundmap = new TreeMap<String, String>();
		refundmap.put("appid", Params.AppID);// 微信公众号ID
		refundmap.put("mch_id", Params.MchId);// 商户号ID
		refundmap.put("nonce_str", Params.getRandomString(32));// 随机字符串 （32）位
		refundmap.put("out_trade_no", "ceshiwangjun002");// 商户退款
		refundmap.put("out_refund_no", Uuid.getUUID());// 商户退款生成的单号
		refundmap.put("total_fee", total_fee + "");
		refundmap.put("refund_fee", refund_fee + "");
		String sign = PayCommonUtil.createSign("UTF-8", refundmap, Params.partnerkey);
		refundmap.put("sign", sign);
		
		System.out.println(refundmap);
		System.out.println("退款报文:" + Params.mapToXml(refundmap));
		System.err.println("商户ID："+Params.MchId);
		@SuppressWarnings("unused")
		String result;
		try {
			result = WeixinSendPost(Params.mapToXml(refundmap), Params.MchId);
			System.out.println(Params.mapToXml(refundmap));
		} catch (Exception e) {
			
			e.printStackTrace();
		}
	}

	public static String WeixinSendPost(Object xmlObj, String mch_id) throws IOException, KeyStoreException,
			UnrecoverableKeyException, NoSuchAlgorithmException, KeyManagementException {
		String result = "";
		String path=WeChatConytoller.class.getResource("/").getPath();
		InputStream instream = new FileInputStream(path+"apiclient_cert.p12"); 
		System.out.println(instream);
		KeyStore keyStore = KeyStore.getInstance("PKCS12");
		try {
			keyStore.load(instream, mch_id.toCharArray());
		} catch (CertificateException e) {
			e.printStackTrace();
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} finally {
			instream.close();
		}
		javax.net.ssl.SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, mch_id.toCharArray())
				.build();

		SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext, new String[] { "TLSv1" }, null,
				SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
		CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
		try {
			HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/secapi/pay/refund");
			HttpEntity xmlData = new StringEntity((String) xmlObj, "text/xml", "iso-8859-1");
			httpPost.setEntity(xmlData);

			System.out.println("executing request" + httpPost.getRequestLine());

			CloseableHttpResponse response = httpclient.execute(httpPost);
			try {
				HttpEntity entity = response.getEntity();
				result = EntityUtils.toString(entity, "UTF-8");
				System.out.println(response.getStatusLine());
				EntityUtils.consume(entity);
			} finally {
				response.close();
			}
		} finally {
			httpclient.close();
		} // 去除空格
		return result.replaceAll(" ", "");
	}

	
}
